package com.sso.manager;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sso.common.enums.SysResourceEnum;
import com.sso.entity.SysResource;
import com.sso.exception.SelectException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.tools.util.StrUtils;
import com.sso.common.ConstantDate;
import com.sso.common.enums.FlagStatus;
import com.sso.common.enums.SysMenuEnum;
import com.sso.dao.SysMenuMapper;
import com.sso.entity.SysMenu;
import com.sso.entity.vo.SysMenuVo;

@Service("sysMenuManager")
public class SysMenuManager {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	@Autowired
	private SysMenuMapper menuDao;
	@Autowired
	private SysMenuRoleManager menuRoleManager;
	@Autowired
	private SysUserMenuManager userMenuManager;
	@Autowired
	private SysResourceManager resourceManager;

	/**
	 * 新增或修改菜单
	 * 保存菜单的时候先
	 * @param menu
	 * @return
	 * @throws Exception
     */
	@Transactional(rollbackFor = Exception.class)
	public String save(SysMenu menu) throws Exception{
		if(StrUtils.isEmpty(menu.getId())){
			this.insert(menu);
		}else{
			this.update(menu);
		}
		return FlagStatus.SUCCESS.value;
	}
	@Transactional(rollbackFor = Exception.class)
	public String bindResource(SysMenu menu,SysResource resource) throws Exception {
		menu.setResourceId(resource.getId());
		resource.setAuthType(SysResourceEnum.AuthType.DEFAULT.key);
		resource.setStatus(SysResourceEnum.status.START.key);
		this.resourceManager.saveResource(resource);
		this.save(menu);
		return FlagStatus.SUCCESS.value;
	}

	@Transactional(rollbackFor = Exception.class)
	public String unBindRsource(SysMenu menu) throws Exception {
		//请空菜单所绑定的资源
		menu.setResourceId("");
		//更改该资源的权限类型
		this.updateResourceAuthType(menu.getResourceId(),SysResourceEnum.AuthType.LOGIN.key);
		//更新菜单信息
		this.save(menu);
		return FlagStatus.SUCCESS.value;
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	public List<SysMenu> selectByProperty(Map<String,Object> filterMap){
		return menuDao.selectByProperty(filterMap);
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	public SysMenu selectByCname(String cname){
		Map<String,Object> param = new HashMap<String, Object>();
		param.put("cname",cname);
		return this.selectByUnique(param);
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	public SysMenu selectByEname(String ename){
		Map<String,Object> param = new HashMap<String, Object>();
		param.put("ename",ename);
		return this.selectByUnique(param);
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	public SysMenu selectById(String id){
		SysMenu menu = new SysMenu();
		Map<String,Object> filterMap = new HashMap<String, Object>();
		filterMap.put("id", id);
		return this.selectByUnique(filterMap);
	}

	/**
	 * 唯一条件查询，查询条件必须使用唯一查询，否则报错
	 * @param param
	 * @return
     */
	@Transactional(propagation = Propagation.SUPPORTS)
	private SysMenu selectByUnique(Map<String,Object> param){
		SysMenu menu = new SysMenu();
		List<SysMenu> list = this.selectByProperty(param);
		if(list.size()>1 || list.size()==0){
			logger.info("查询数据量过大:list.size大小="+list.size());
		}else{
			menu = list.get(0);
		}
		return menu;
	}

	@Transactional(rollbackFor = Exception.class)
	public void deleteById(SysMenu menu)throws Exception{
		//删除菜单角色表关联数据
		this.menuRoleManager.deleteByMenuId(menu.getId());
		//删除用户菜单表关联数据
		this.userMenuManager.deleteByMenuId(menu.getId());
		Map<String,Object> param = new HashMap<String, Object>();
		param.put("parentMenuId",menu.getParentMenuId());
		List<SysMenu> list = this.selectByProperty(param);
		list.remove(menu.getSequence()-1);
		//全部循环
		for(int i=0;i<list.size();i++){
			if(list.get(i).getSequence()>=menu.getSequence()) {
				list.get(i).setSequence(list.get(i).getSequence() - 1);
			}else{
				list.remove(list.get(i));
				--i;
			}
		}
		this.menuDao.delete(menu.getId());
		this.updateResourceAuthType(menu.getResourceId(),SysResourceEnum.AuthType.LOGIN.key);
		if(list.size()>0) {
			this.menuDao.updateBatch(list);
		}
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	public List<SysMenuVo> selectVoByProperty(Map<String,Object> filterMap){
		return menuDao.selectVoByProperty(filterMap);
	}

	private String insert(SysMenu menu) throws Exception {
		if(StrUtils.isEmpty(menu.getParentMenuId())){
			menu.setParentMenuId("0");
		}
		if(StrUtils.isNotEmpty(menu.getParentMenuId())){
			SysMenu parentMenu = this.selectById(menu.getParentMenuId());
			int level = Integer.parseInt(StrUtils.doNull(parentMenu.getLevelNum(),"0"))+1;
			menu.setLevelNum(String.valueOf(level));
		}
		menu.setId(ConstantDate.getUUID());
		menu.setStatus(SysMenuEnum.status.DISCARD.key);
		menu.setCreateTime(new Date());
		Map<String,Object> param = new HashMap<String, Object>();

		//没有父节点表示是第一级菜单
		if(StrUtils.isEmpty(menu.getParentMenuId())){
			param.put("levelNum",SysMenuEnum.levelNumEnum.FIRST.value);
		}else{
			param.put("parentMenuId",menu.getParentMenuId());
		}
		List<SysMenu> list = this.selectByProperty(param);
		//如果新菜单的的序列大于菜单总数则排最后一个。
		if(list.size()<menu.getSequence()){
			menu.setSequence(list.size()+1);
		}
		list.add(menu.getSequence()-1,menu);
		//处理菜单序列问题
		for(int i=0;i<list.size();i++){
			list.get(i).setSequence(i+1);
		}
		menuDao.insert(menu);
		menuDao.updateBatch(list);
		return FlagStatus.SUCCESS.value;
	}
	private String update(SysMenu menu) throws Exception {
		//查询以前的数据
		SysMenu oldMenu = this.selectById(menu.getId());
		if(StrUtils.isEmpty(oldMenu.getId())){
			return FlagStatus.ERROR.value;
		}
		//判断当修改后的菜单序列与原菜单序列不相同时先要处理菜单序列问题再进行批量更新
		if(oldMenu.getSequence()!=menu.getSequence()) {
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("parentMenuId", oldMenu.getParentMenuId());
			List<SysMenu> list = this.selectByProperty(param);
			//删除原先位置，插入到新位置
			list.remove(oldMenu.getSequence()-1);
			list.add(menu.getSequence() - 1, menu);
			for (int i = 0; i < list.size(); i++) {
				list.get(i).setSequence(i + 1);
			}
			menuDao.updateBatch(list);
		}else{
			menuDao.update(menu);
		}
		return FlagStatus.SUCCESS.value;
	}

	private void updateResourceAuthType(String resId,String auth) throws Exception {
		SysResource resource = resourceManager.selectByid(resId);
		resource.setAuthType(auth);
		resourceManager.saveResource(resource);
	}
}
